#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>

void sys_error_check(const int ret, const char *msg)
{
    if (ret < 0)
    {
        perror(msg);
        exit(EXIT_FAILURE);
    }
}
void *read_from_server(void *serverfd)
{
    char *buf = NULL;
    int client = *(int *)serverfd;
    buf = malloc(sizeof(char) * 1024);
    // receive
    int count;
    while (1)
    {
        count = recv(client, buf, 1024, 0);
        if (count <= 0)
        {
            perror("read error");
            break;
        }
        printf("%s", buf);
    }
    printf("read thread exit\n");
    free(buf);
}
void *write_to_server(void *serverfd)
{
    char *buf = NULL;
    int client = *(int *)serverfd;
    buf = malloc(sizeof(char) * 1024);
    int count;
    while (fgets(buf, 1024, stdin) != NULL)
    {
        count = send(client, buf, 1024, 0);
        if (count < 0)
        {
            perror("write failed");
        }
        printf("input closed\n");
    }
    shutdown(client, SHUT_WR);
    free(buf);
}
int main(int argc, char const *argv[])
{
    int sockfd, ret;
    pthread_t pid1, pid2;
    struct sockaddr_in server_addr, client_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    memset(&client_addr, 0, sizeof(client_addr));

    client_addr.sin_family = AF_INET;
    inet_pton(AF_INET, "192.168.31.191", &client_addr.sin_addr);
    client_addr.sin_port = htons(56322); //与服务端不同
    server_addr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr.s_addr);
    server_addr.sin_port = htons(56321); 
    
    // create
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    sys_error_check(sockfd, "socket");
    ret = bind(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr));
    sys_error_check(ret, "bind");
    ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    sys_error_check(ret, "connect");
    printf("connect to server %s:%d\n", inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port));

    // create thread
    pthread_create(&pid1, NULL, read_from_server, (void *)&sockfd);
    pthread_create(&pid2, NULL, write_to_server, (void *)&sockfd);

    pthread_join(pid1, NULL);
    pthread_join(pid2, NULL);
    close(sockfd);
    return 0;
}
